﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using KC.Framework.Extension;
using IdentityServer4;
using IdentityServer4.Models;
using KC.Framework.Tenant;
using KC.MVC.Core.Constants;

namespace KC.Web.SSO
{
    public class IdentityServerConfig
    {
        public static IEnumerable<Tenant> TenantsForTest = new List<Tenant>(new[]
        {
            TenantConstant.DbaTenantApiAccessInfo,
            TenantConstant.TestTenantApiAccessInfo,
            TenantConstant.BuyTenantApiAccessInfo,
            TenantConstant.SaleTenantApiAccessInfo
        });

        // scopes define the resources in your system
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
            };
        }

        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource(ApplicationConstant.SsoScope, ApplicationConstant.SsoAppName),
                new ApiResource(ApplicationConstant.AdminScope, ApplicationConstant.AdminAppName),
                new ApiResource(ApplicationConstant.BlogScope, ApplicationConstant.BlogAppName),

                new ApiResource(ApplicationConstant.AppScope, ApplicationConstant.AppAppName),
                new ApiResource(ApplicationConstant.CfgScope, ApplicationConstant.ConfigAppName),
                new ApiResource(ApplicationConstant.DicScope, ApplicationConstant.DictAppName),
                new ApiResource(ApplicationConstant.MsgScope, ApplicationConstant.MsgAppName),

                new ApiResource(ApplicationConstant.AccScope, ApplicationConstant.AccAppName),
                new ApiResource(ApplicationConstant.EconScope, ApplicationConstant.EconAppName),
                new ApiResource(ApplicationConstant.DocScope, ApplicationConstant.DocAppName),
                new ApiResource(ApplicationConstant.HrScope, ApplicationConstant.HrAppName),

                new ApiResource(ApplicationConstant.CrmScope, ApplicationConstant.CrmAppName),
                new ApiResource(ApplicationConstant.SrmScope, ApplicationConstant.SrmAppName),
                new ApiResource(ApplicationConstant.PrdScope, ApplicationConstant.PrdAppName),
                new ApiResource(ApplicationConstant.PmcScope, ApplicationConstant.PmcAppName),

                new ApiResource(ApplicationConstant.PortalScope, ApplicationConstant.PortalAppName),
                new ApiResource(ApplicationConstant.SomScope, ApplicationConstant.SomAppName),
                new ApiResource(ApplicationConstant.PomScope, ApplicationConstant.PomAppName),
                new ApiResource(ApplicationConstant.WmsScope, ApplicationConstant.WmsAppName),

                new ApiResource(ApplicationConstant.MarketScope, ApplicationConstant.MarketAppName),
                new ApiResource(ApplicationConstant.TrainScope, ApplicationConstant.TrainAppName),

                new ApiResource(ApplicationConstant.FlowScope, ApplicationConstant.FlowAppName),
                new ApiResource(ApplicationConstant.PayScope, ApplicationConstant.PayAppName),
                new ApiResource(ApplicationConstant.WXScope, ApplicationConstant.WXAppName),

            };
        }

        //private static DateTime _defaultExpiredTime = DateTime.Now.AddMonths(1);
        private static DateTime _defaultExpiredTime = DateTime.Now.AddMinutes(15);
        // clients want to access resources (aka scopes)
        public static IEnumerable<Client> GetClients()
        {
            var result = new List<Client>();
            result.Add(new Client
            {
                ClientId = OpenIdConnectConstants.TestClient_ClientId,
                ClientName = OpenIdConnectConstants.TestClient_ClientId,
                ClientSecrets =
                {
                    new Secret(OpenIdConnectConstants.TestClient_ClientSecret.Sha256())
                },
                Enabled = true,
                RequireConsent = false,
                AllowedGrantTypes = GrantTypes.ClientCredentials,
                AllowAccessTokensViaBrowser = true,

                //AllowedCorsOrigins = new List<string>() { "*" },

                AccessTokenLifetime = 60 * 60,//1 hours
                AccessTokenType = AccessTokenType.Jwt,

                AlwaysIncludeUserClaimsInIdToken = true,
                IdentityTokenLifetime = Service.Core.Constants.TimeOutConstants.CookieTimeOut * 60,// 15 minutes

                AllowedScopes = { ApplicationConstant.AdminScope, ApplicationConstant.AppScope, ApplicationConstant.AccScope, ApplicationConstant.EconScope, ApplicationConstant.DocScope, ApplicationConstant.CfgScope, ApplicationConstant.DicScope, ApplicationConstant.MsgScope, ApplicationConstant.CrmScope, ApplicationConstant.SrmScope, ApplicationConstant.PrdScope, ApplicationConstant.PmcScope, ApplicationConstant.PortalScope, ApplicationConstant.SomScope, ApplicationConstant.PomScope, ApplicationConstant.WmsScope, ApplicationConstant.FlowScope, ApplicationConstant.PayScope, ApplicationConstant.WXScope, ApplicationConstant.MarketScope, ApplicationConstant.BlogScope }
            });

            result.Add(new Client
            {
                ClientId = OpenIdConnectConstants.WebApiTestClient_ClientId,
                ClientName = "api's swagger test",
                Enabled = true,
                AllowedGrantTypes = GrantTypes.Implicit,
                AllowAccessTokensViaBrowser = true,
                RequireConsent = false,

                AccessTokenLifetime = Service.Core.Constants.TimeOutConstants.AccessTokenTimeOut * 60,//1 hours
                AccessTokenType = AccessTokenType.Jwt,

                AlwaysIncludeUserClaimsInIdToken = true,
                IdentityTokenLifetime = Service.Core.Constants.TimeOutConstants.CookieTimeOut * 60,// 15 minutes

                RedirectUris = {
                    "http://localhost:1004/oauth2-redirect.html",//com.webapi.admin
                    "http://localhost:1006/oauth2-redirect.html",//com.webapi.app
                    "http://cdba.localhost:1004/oauth2-redirect.html",//com.webapi.admin
                    "http://cdba.localhost:1006/oauth2-redirect.html",//com.webapi.app
                    "http://cdba.localhost:1102/oauth2-redirect.html",//com.webapi.config
                    "http://cdba.localhost:1104/oauth2-redirect.html",//com.webapi.dict
                    "http://cdba.localhost:2002/oauth2-redirect.html",//com.webapi.account

                    "http://ctest.localhost:1004/oauth2-redirect.html",//com.webapi.admin
                    "http://ctest.localhost:1006/oauth2-redirect.html",//com.webapi.app
                    "http://ctest.localhost:1102/oauth2-redirect.html",//com.webapi.config
                    "http://ctest.localhost:1104/oauth2-redirect.html",//com.webapi.dict
                    "http://ctest.localhost:2002/oauth2-redirect.html",//com.webapi.account

                    "http://cbuy.localhost:1004/oauth2-redirect.html",//com.webapi.admin
                    "http://cbuy.localhost:1006/oauth2-redirect.html",//com.webapi.app
                    "http://cbuy.localhost:1102/oauth2-redirect.html",//com.webapi.config
                    "http://cbuy.localhost:1104/oauth2-redirect.html",//com.webapi.dict
                    "http://cbuy.localhost:2002/oauth2-redirect.html",//com.webapi.account

                    "http://testadminapi.kcloudy.com/oauth2-redirect.html",//com.webapi.admin
                    "http://testappapi.kcloudy.com/oauth2-redirect.html",//com.webapi.app
                    "http://cdba.testcfgapi.kcloudy.com/oauth2-redirect.html",//com.webapi.config
                    "http://cdba.testdicapi.kcloudy.com/oauth2-redirect.html",//com.webapi.dict
                    "http://cdba.testaccapi.kcloudy.com/oauth2-redirect.html",//com.webapi.account

                    "http://ctest.testcfgapi.kcloudy.com/oauth2-redirect.html",//com.webapi.config
                    "http://ctest.testdicapi.kcloudy.com/oauth2-redirect.html",//com.webapi.dict
                    "http://ctest.testaccapi.kcloudy.com/oauth2-redirect.html",//com.webapi.account

                    "http://betaadminapi.kcloudy.com/oauth2-redirect.html",//com.webapi.admin
                    "http://betaappapi.kcloudy.com/oauth2-redirect.html",//com.webapi.app
                    "http://cdba.betacfgapi.kcloudy.com/oauth2-redirect.html",//com.webapi.config
                    "http://cdba.betadicapi.kcloudy.com/oauth2-redirect.html",//com.webapi.dict
                    "http://cdba.betaaccapi.kcloudy.com/oauth2-redirect.html",//com.webapi.account

                    "http://ctest.betacfgapi.kcloudy.com/oauth2-redirect.html",//com.webapi.config
                    "http://ctest.betadicapi.kcloudy.com/oauth2-redirect.html",//com.webapi.dict
                    "http://ctest.betaaccapi.kcloudy.com/oauth2-redirect.html",//com.webapi.account

                    "http://adminapi.kcloudy.com/oauth2-redirect.html",//com.webapi.admin
                    "http://appapi.kcloudy.com/oauth2-redirect.html",//com.webapi.app
                    "http://cdba.cfgapi.kcloudy.com/oauth2-redirect.html",//com.webapi.config
                    "http://cdba.dicapi.kcloudy.com/oauth2-redirect.html",//com.webapi.dict
                    "http://cdba.accapi.kcloudy.com/oauth2-redirect.html",//com.webapi.account

                    "http://ctest.cfgapi.kcloudy.com/oauth2-redirect.html",//com.webapi.config
                    "http://ctest.dicapi.kcloudy.com/oauth2-redirect.html",//com.webapi.dict
                    "http://ctest.accapi.kcloudy.com/oauth2-redirect.html",//com.webapi.account
                     },
                AllowedScopes = { ApplicationConstant.AdminScope, ApplicationConstant.AppScope, ApplicationConstant.AccScope, ApplicationConstant.EconScope, ApplicationConstant.DocScope, ApplicationConstant.CfgScope, ApplicationConstant.DicScope, ApplicationConstant.MsgScope, ApplicationConstant.CrmScope, ApplicationConstant.SrmScope, ApplicationConstant.PrdScope, ApplicationConstant.PmcScope, ApplicationConstant.PortalScope, ApplicationConstant.SomScope, ApplicationConstant.PomScope, ApplicationConstant.WmsScope, ApplicationConstant.FlowScope, ApplicationConstant.PayScope, ApplicationConstant.WXScope, ApplicationConstant.MarketScope, ApplicationConstant.BlogScope }
            });

            foreach (var tenant in TenantsForTest)
            {
                //tenant.Hostnames = TenantConstant.GetTenantHosts(tenant.TenantName);
                var postLogoutUrls = tenant.Hostnames.ToList();
                var redirectUrls = tenant.Hostnames.Select(m => m.TrimEndSlash() + MVC.Core.Constants.OpenIdConnectConstants.CallbackPath).ToList();
                var frontLogoutCallbackUrl = tenant.Hostnames.FirstOrDefault().TrimEndSlash() + MVC.Core.Constants.OpenIdConnectConstants.SignOutPath;

                //for java spring security
                redirectUrls.AddRange(tenant.Hostnames.Select(m => m.TrimEndSlash() + MVC.Core.Constants.OpenIdConnectConstants.JavaCallbackPath).ToList());
                //for java swagger security
                redirectUrls.AddRange(tenant.Hostnames.Select(m => m.TrimEndSlash() + MVC.Core.Constants.OpenIdConnectConstants.JavaSwaggerCallbackPath).ToList());

                result.Add(new Client
                {
                    ClientName = tenant.TenantName,
                    ClientId = TenantConstant.GetClientIdByTenant(tenant),
                    ClientSecrets =
                    {
                        new Secret(TenantConstant.GetClientSecretByTenant(tenant).Sha256())
                        //new Secret(TenantConstant.GetClientSecretByTenant(tenant))
                    },
                    Enabled = true,

                    // RequireClientSecret might as well be true if you are giving this client a secret
                    //RequireClientSecret = true,

                    RequireConsent = false,
                    AllowOfflineAccess = true,

                    FrontChannelLogoutSessionRequired = true,
                    FrontChannelLogoutUri = frontLogoutCallbackUrl,

                    //对应客户端设置：
                    //Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectOptions.CallbackPath
                    RedirectUris = redirectUrls,
                    //对应客户端设置：
                    //Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectOptions.RemoteSignOutPath
                    PostLogoutRedirectUris = postLogoutUrls,

                    AllowAccessTokensViaBrowser = true,
                    AccessTokenLifetime = 60 * 60,//1 hours
                    AccessTokenType = AccessTokenType.Jwt,

                    AlwaysIncludeUserClaimsInIdToken = true,
                    IdentityTokenLifetime = Service.Core.Constants.TimeOutConstants.CookieTimeOut * 60,// 20 minutes

                    //AllowedCorsOrigins = new List<string>() { "*" },

                    RefreshTokenUsage = TokenUsage.OneTimeOnly,
                    RefreshTokenExpiration = TokenExpiration.Sliding,

                    AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
                    //AllowedGrantTypes = GrantTypes.Hybrid,
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.OfflineAccess,
                        ApplicationConstant.AdminScope, ApplicationConstant.AppScope, ApplicationConstant.AccScope, ApplicationConstant.EconScope, ApplicationConstant.DocScope, ApplicationConstant.CfgScope, ApplicationConstant.DicScope, ApplicationConstant.MsgScope, ApplicationConstant.CrmScope, ApplicationConstant.SrmScope, ApplicationConstant.PrdScope, ApplicationConstant.PmcScope, ApplicationConstant.PortalScope, ApplicationConstant.SomScope, ApplicationConstant.PomScope, ApplicationConstant.WmsScope, ApplicationConstant.FlowScope, ApplicationConstant.PayScope, ApplicationConstant.WXScope, ApplicationConstant.MarketScope, ApplicationConstant.BlogScope
                    }
                });
            }
            return result;
        }
    }
}
